home *** CD-ROM | disk | FTP | other *** search
Wrap
#define STRICT // Includes standard Windows #include <windows.h> #include <windowsx.h> #include <time.h> #include <stdlib.h> #include <malloc.h> #include <memory.h> #include <stdio.h> // Includes D3D #define D3D_OVERLOADS #include <ddraw.h> #include <d3d.h> #include <d3dx.h> // Includes utilitaires D3D #include "d3dmath.h" #include "d3dutil.h" #include "D3DEnum.h" // Ids Resources #include "resource.h" // Constantes #include "const.h" // Types #include "types.h" // Variables globales projet #include "vars.h" // Prototypes fonctions autres modules #include "proto.h" // Macros #include "macros.h" // Variables statiques au module static BOOL bTracking = FALSE; // Poursuite curseur en cours o/n (WM_LBUTTONDOWN / WM_MOUSEMOVE) static WPARAM wModifier; // Mémorisé sur le LBUTTONDOWN : SHIFT / CTRL / ... static HBRUSH hbrDkBlueSk, hbrLtBlueSk; // Brosses de remplissage static HPEN hpenWhite, hpenGrey, hpenCyan, hpenYellow, hpenPink, hpenDkBlueSk, hpenRed; // Crayons static HFONT hFont; // Forcer le redessin des 3 vues 2D (WM_PAINT) // Le paramètre sert à indiquer s'il faut tout redessiner (y/c triangles & sommets) -> TRUE // ou s'il ne faut redessiner que les curseurs, caméra & target void vForce2DRefresh(BOOL bMode) { PostMessage(hWndTop, WM_PAINT, 0, (LPARAM) bMode); PostMessage(hWndFace, WM_PAINT, 0, (LPARAM) bMode); PostMessage(hWndRight, WM_PAINT, 0, (LPARAM) bMode); } // Callback management fenêtres vues 2D LRESULT CALLBACK lrPlanarWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // Variables locales (Attention, réinitialiser à chaque fois : pas d'existence en dehors du traitement d'un message) WinThings *pWT; // Pointeur sur structure étendue fenêtre (double buffer, gadgets etc.) PAINTSTRUCT hPStruct; // Pour WM_PAINT HDC hdcWin= GetDC(hWnd); // DC fenêtre RECT rExtRect, rIntRect; // Zones client externe (avec gadgets) et interne (zone de dessin uniquement) HBRUSH hSaveBrush; // Pour restaurer dans le HDC du double buffer HPEN hSavePen; // Pour restaurer dans le HDC du double buffer // Autres variables à usage général register int iX, iY, iZ, iT, iWindowXMin, iWindowXMax, iWindowYMin, iWindowYMax; float fXs, fYs, fZs, f3D2DXCoef, f3D2DYCoef; HDC hdcDoubleBuf, hdcTripleBuf; D3DVECTOR vVect1, vVect2; POINT pClick; COLORREF lColor; char cCoords[80]; HMENU hMenu; char cAxis; // Récupérer notre identifiant (vue dessus, face, droite) et mémoriser dans une globale pour que les autres fonctions sachent quelle fenêtre 2D est active lWActive = GetWindowLong(hWnd, GWL_USERDATA); // Récupérer le rectangle complet de la zone client de la fenêtre GetClientRect(hWnd, &rExtRect); // Cloner ce rectangle et le réduire pour laisser la place aux gadgets CopyRect(&rIntRect, &rExtRect); InflateRect(&rIntRect, -XDC_G_LARG, -XDC_G_HAUT); // Précalculer les coefficients de pente de conversion 3D/2D et déréférencer les coordonnées de la fenêtre iWindowXMin = rIntRect.left; iWindowXMax = rIntRect.right; iWindowYMax = rIntRect.top; iWindowYMin = rIntRect.bottom; switch(lWActive) { case XDC_WID_TOP : // X et Z f3D2DXCoef = (float) (iWindowXMax - iWindowXMin) / (fXmax - fXmin); f3D2DYCoef = (float) (iWindowYMax - iWindowYMin) / (fZmax - fZmin); break; case XDC_WID_FACE : // X et Y f3D2DXCoef = (float) (iWindowXMax - iWindowXMin) / (fXmax - fXmin); f3D2DYCoef = (float) (iWindowYMax - iWindowYMin) / (fYmax - fYmin); break; case XDC_WID_SIDE : // Z et Y f3D2DXCoef = (float) (iWindowXMax - iWindowXMin) / (fZmax - fZmin); f3D2DYCoef = (float) (iWindowYMax - iWindowYMin) / (fYmax - fYmin); break; } // Récupérer le pointeur sur la structure de données étendue de la fenêtre (double & triple buffer, gadgets etc.) pWT = (WinThings *) GetWindowLong(hWnd, 0); switch( uMsg ) { case WM_CREATE: //************************* C R E A T E ************************ // Allouer les objets GDI (globaux à toutes les fenêtres 2D d'où if ...) if (!hpenWhite) hpenWhite = CreatePen(PS_SOLID, 1, XDC_COL_WHITE); if (!hpenRed) hpenRed = CreatePen(PS_SOLID, 1, XDC_COL_RED); if (!hpenYellow) hpenYellow = CreatePen(PS_SOLID, 1, XDC_COL_YELLOW); if (!hpenCyan) hpenCyan = CreatePen(PS_SOLID, 1, XDC_COL_CYAN); if (!hpenPink) hpenPink = CreatePen(PS_SOLID, 1, XDC_COL_PINK); if (!hpenGrey) hpenGrey = CreatePen(PS_SOLID, 1, XDC_COL_GREY); if (!hbrDkBlueSk) hbrDkBlueSk = CreateSolidBrush(XDC_COL_DKBLUESK); if (!hbrLtBlueSk) hbrLtBlueSk = CreateSolidBrush(XDC_COL_LTBLUESK); if (!hpenDkBlueSk) hpenDkBlueSk = CreatePen(PS_SOLID, 1, XDC_COL_DKBLUESK); // Créer la fonte pour indiquer l'outil en cours à coté du curseur if (!hFont) hFont = CreateFont( -12, 0, 0, 0, FW_BOLD, TRUE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, VARIABLE_PITCH, "Arial" ); // Créer la structure de données étendue et l'attacher à la fenêtre if (!(pWT = (WinThings *) malloc(sizeof(WinThings)))) { // Si fail, sortir de l'application PostQuitMessage(0); break; } SetWindowLong(hWnd, 0, (long) pWT); // Créer le double buffer et l'attacher à la structure de données étendue pWT -> hdcDBuf = CreateCompatibleDC(hdcWin); pWT -> hbDBuf = CreateCompatibleBitmap(hdcWin, rExtRect.right - rExtRect.left + 1, rExtRect.bottom - rExtRect.top +1); pWT -> holdDFont = (HFONT) SelectObject(pWT -> hdcDBuf, hFont); pWT -> holdDBuf = SelectObject(pWT -> hdcDBuf, pWT -> hbDBuf); SetBkMode(pWT -> hdcDBuf, TRANSPARENT); SetTextColor(pWT -> hdcDBuf, XDC_COL_YELLOW); // Créer le triple buffer et l'attacher à la structure de données étendue pWT -> hdcTBuf = CreateCompatibleDC(hdcWin); pWT -> hbTBuf = CreateCompatibleBitmap(hdcWin, rExtRect.right - rExtRect.left + 1, rExtRect.bottom - rExtRect.top +1); pWT -> holdTBuf = SelectObject(pWT -> hdcTBuf, pWT -> hbTBuf); pWT -> holdTBrush = (HBRUSH) SelectObject(pWT -> hdcTBuf, hbrLtBlueSk); pWT -> holdTFont = (HFONT) SelectObject(pWT -> hdcTBuf, hFont); SetBkMode(pWT -> hdcTBuf, TRANSPARENT); SetTextColor(pWT -> hdcTBuf, XDC_COL_YELLOW); // Initialiser les pointeurs de gadgets sur l'imagerie gadgets (commune à toutes les fenêtres) pWT -> Widgets[XDC_GID_AddPoint].Gad = &gAddPoint; pWT -> Widgets[XDC_GID_Center].Gad = &gCenter; pWT -> Widgets[XDC_GID_GoDown].Gad = &gGoDown; pWT -> Widgets[XDC_GID_GoLeft].Gad = &gGoLeft; pWT -> Widgets[XDC_GID_GoUp].Gad = &gGoUp; pWT -> Widgets[XDC_GID_GoRight].Gad = &gGoRight; pWT -> Widgets[XDC_GID_Grab].Gad = &gGrab; pWT -> Widgets[XDC_GID_MakeTri].Gad = &gMakeTri; pWT -> Widgets[XDC_GID_Reverse].Gad = &gReverse; pWT -> Widgets[XDC_GID_RotAnti].Gad = &gRotAnti; pWT -> Widgets[XDC_GID_RotClock].Gad = &gRotClock; pWT -> Widgets[XDC_GID_ZoomIn].Gad = &gZoomIn; pWT -> Widgets[XDC_GID_ZoomOut].Gad = &gZoomOut; // Se rappeler que le prochain WM_PAINT sera le premier pWT -> bFirstPaint = TRUE; break; case WM_USER + 1: //*********************** Rafraichir le point d'indice wParam dans le double buffer // (-> refresh 2D mode partiel à suivre) hdcDoubleBuf = pWT -> hdcDBuf; vVect1 = Vertices[wParam].vPoint; switch(lWActive) { case XDC_WID_TOP : // X et Z iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(vVect1.z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y iX = (int) XDM_to2D(vVect1.z, fZmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); break; } // Tracer le sommet du triangle (petite croix) lColor = Vertices[wParam].bSelected ? XDC_COL_YELLOW : XDC_COL_DKBLUESK; SetPixel(hdcDoubleBuf, iX, iY, lColor); SetPixel(hdcDoubleBuf, iX - 1, iY, lColor); SetPixel(hdcDoubleBuf, iX + 1, iY, lColor); SetPixel(hdcDoubleBuf, iX, iY - 1, lColor); SetPixel(hdcDoubleBuf, iX, iY + 1, lColor); break; case WM_PAINT: //************************** P A I N T *********************** { // déréférencer les HDC du double et du triple buffer pour aller plus vite hdcDoubleBuf = pWT -> hdcDBuf; hdcTripleBuf = pWT -> hdcTBuf; BeginPaint(hWnd, &hPStruct); // On redessine tout seulement si on nous le demande ou si c'est le premier WM_PAINT if (((BOOL) lParam || pWT -> bFirstPaint) == XDC_MODE_PARTIEL) goto _skip; // Se rappeller que les WM_PAINT à venir ne sont pas les premiers pWT -> bFirstPaint = FALSE; // Remplir le grand rectangle en bleu foncé FillRect(hdcDoubleBuf, &rExtRect, hbrDkBlueSk); // Remplir le petit rectangle en bleu clair avec tour blanc hSaveBrush = (HBRUSH) SelectObject(hdcDoubleBuf, hbrLtBlueSk); hSavePen = (HPEN) SelectObject(hdcDoubleBuf, hpenWhite); Rectangle(hdcDoubleBuf, iWindowXMin, iWindowYMin, iWindowXMax, iWindowYMax); // Ajouter tous les gadgets Sculpt3D XDM_Bouton(pWT -> Widgets[XDC_GID_AddPoint], 0, 11); XDM_Bouton(pWT -> Widgets[XDC_GID_Center], XDC_G_LARG + 4, rExtRect.bottom - XDC_G_HAUT); XDM_Bouton(pWT -> Widgets[XDC_GID_GoDown], (rExtRect.right - rExtRect.left) / 2 - 8, rExtRect.bottom - XDC_G_HAUT); XDM_Bouton(pWT -> Widgets[XDC_GID_GoLeft], 0, (rExtRect.bottom - rExtRect.top) / 2 - 4); XDM_Bouton(pWT -> Widgets[XDC_GID_GoUp], (rExtRect.right - rExtRect.left) / 2 - 8, 0); XDM_Bouton(pWT -> Widgets[XDC_GID_GoRight], rExtRect.right - XDC_G_LARG, (rExtRect.bottom - rExtRect.top) / 2 - 4); XDM_Bouton(pWT -> Widgets[XDC_GID_Grab], 0, rExtRect.bottom - XDC_G_HAUT); XDM_Bouton(pWT -> Widgets[XDC_GID_MakeTri], 0, rExtRect.bottom - 20); XDM_Bouton(pWT -> Widgets[XDC_GID_Reverse], rExtRect.right - XDC_G_LARG, 16); XDM_Bouton(pWT -> Widgets[XDC_GID_RotAnti], 0, 0); XDM_Bouton(pWT -> Widgets[XDC_GID_RotClock], XDC_G_LARG + 2, 0); XDM_Bouton(pWT -> Widgets[XDC_GID_ZoomIn], rExtRect.right - 36, rExtRect.bottom - XDC_G_HAUT); XDM_Bouton(pWT -> Widgets[XDC_GID_ZoomOut], rExtRect.right - XDC_G_LARG, rExtRect.bottom - 20); // Ecrire les noms des axes switch(lWActive) { case XDC_WID_TOP : // Axes X (gauche > droite) et Z (bas > haut) cAxis = 'z'; ExtTextOut(hdcDoubleBuf, (rExtRect.right - rExtRect.left) / 2 + 12, -4, 0, NULL, &cAxis, 1, NULL); cAxis = 'x'; ExtTextOut(hdcDoubleBuf, rExtRect.right - XDC_G_LARG + 5, (rExtRect.bottom - rExtRect.top) / 2 + 4, 0, NULL, &cAxis, 1, NULL); break; case XDC_WID_FACE : // Axes X (gauche > droite) et Y (bas > haut) cAxis = 'y'; ExtTextOut(hdcDoubleBuf, (rExtRect.right - rExtRect.left) / 2 + 12, -4, 0, NULL, &cAxis, 1, NULL); cAxis = 'x'; ExtTextOut(hdcDoubleBuf, rExtRect.right - XDC_G_LARG + 5, (rExtRect.bottom - rExtRect.top) / 2 + 4, 0, NULL, &cAxis, 1, NULL); break; case XDC_WID_SIDE : // Axes Z (gauche > droite) et Y (bas > haut) cAxis = 'y'; ExtTextOut(hdcDoubleBuf, (rExtRect.right - rExtRect.left) / 2 + 12, -4, 0, NULL, &cAxis, 1, NULL); cAxis = 'z'; ExtTextOut(hdcDoubleBuf, rExtRect.right - XDC_G_LARG + 5, (rExtRect.bottom - rExtRect.top) / 2 + 4, 0, NULL, &cAxis, 1, NULL); break; } // Définir zone de clipping : rectangle interne IntersectClipRect(hdcDoubleBuf,iWindowXMin + 1, iWindowYMax + 1, iWindowXMax - 1, iWindowYMin - 1); // Tracer la grille (si elle est activée) if (bGrid) { switch(lWActive) { case XDC_WID_TOP : // Axes X (gauche > droite) et Z (bas > haut) for (fXs = XDM_toGrid(fXmin) ; fXs <= XDM_toGrid(fXmax) ; fXs += fGridSize) for (fZs = XDM_toGrid(fZmin) ; fZs <= XDM_toGrid(fZmax) ; fZs += fGridSize) SetPixel(hdcDoubleBuf, XDM_to2D(fXs, fXmin, iWindowXMin, f3D2DXCoef), XDM_to2D(fZs, fZmin, iWindowYMin, f3D2DYCoef), XDC_COL_GRID); break; case XDC_WID_FACE : // Axes X (gauche > droite) et Y (bas > haut) for (fXs = XDM_toGrid(fXmin) ; fXs <= XDM_toGrid(fXmax) ; fXs += fGridSize) for (fYs = XDM_toGrid(fYmin) ; fYs <= XDM_toGrid(fYmax) ; fYs += fGridSize) SetPixel(hdcDoubleBuf, XDM_to2D(fXs, fXmin, iWindowXMin, f3D2DXCoef), XDM_to2D(fYs, fYmin, iWindowYMin, f3D2DYCoef), XDC_COL_GRID); break; case XDC_WID_SIDE : // Axes Z (gauche > droite) et Y (bas > haut) for (fZs = XDM_toGrid(fZmin) ; fZs <= XDM_toGrid(fZmax) ; fZs += fGridSize) for (fYs = XDM_toGrid(fYmin) ; fYs <= XDM_toGrid(fYmax) ; fYs += fGridSize) SetPixel(hdcDoubleBuf, XDM_to2D(fZs, fZmin, iWindowXMin, f3D2DXCoef), XDM_to2D(fYs, fYmin, iWindowYMin, f3D2DYCoef), XDC_COL_GRID); break; } } // Tracer les axes du repère, en gris SelectObject(hdcDoubleBuf, hpenGrey); switch(lWActive) { case XDC_WID_TOP : // Axes X (gauche > droite) et Z (bas > haut) iY = (int) XDM_to2D(0, fZmin, iWindowYMin, f3D2DYCoef); MoveToEx(hdcDoubleBuf, iWindowXMax, iY, NULL); LineTo(hdcDoubleBuf, iWindowXMin, iY); iX = (int) XDM_to2D(0, fXmin, iWindowXMin, f3D2DXCoef); MoveToEx(hdcDoubleBuf, iX, iWindowYMin, NULL); LineTo(hdcDoubleBuf, iX, iWindowYMax); break; case XDC_WID_FACE : // Axes X (gauche > droite) et Y (bas > haut) iY = (int) XDM_to2D(0, fYmin, iWindowYMin, f3D2DYCoef); MoveToEx(hdcDoubleBuf, iWindowXMax, iY, NULL); LineTo(hdcDoubleBuf, iWindowXMin, iY); iX = (int) XDM_to2D(0, fXmin, iWindowXMin, f3D2DXCoef); MoveToEx(hdcDoubleBuf, iX, iWindowYMin, NULL); LineTo(hdcDoubleBuf, iX, iWindowYMax); break; case XDC_WID_SIDE : // Axes Z (gauche > droite) et Y (bas > haut) iY = (int) XDM_to2D(0, fYmin, iWindowYMin, f3D2DYCoef); MoveToEx(hdcDoubleBuf, iWindowXMax, iY, NULL); LineTo(hdcDoubleBuf, iWindowXMin, iY); iX = (int) XDM_to2D(0, fZmin, iWindowXMin, f3D2DXCoef); MoveToEx(hdcDoubleBuf, iX, iWindowYMin, NULL); LineTo(hdcDoubleBuf, iX, iWindowYMax); break; } // Tracer les objets géométriques // 1 - Arêtes // Choisir le crayon rouge { SelectObject(hdcDoubleBuf, hpenRed); for (int iEdge = 0 ; iEdge <= iEdgeLastUsed ; iEdge++) { // Ignorer les arêtes inexistants if (Edges[iEdge].bEnabled == FALSE) continue; // Ignorer les arêtes cachés if (Edges[iEdge].bHidden == TRUE) continue; vVect1 = Vertices[Edges[iEdge].iSommets[0]].vPoint; vVect2 = Vertices[Edges[iEdge].iSommets[1]].vPoint; switch(lWActive) { case XDC_WID_TOP : // X et Z iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(vVect1.z, fZmin, iWindowYMin, f3D2DYCoef); iZ = (int) XDM_to2D(vVect2.x, fXmin, iWindowXMin, f3D2DXCoef); iT = (int) XDM_to2D(vVect2.z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); iZ = (int) XDM_to2D(vVect2.x, fXmin, iWindowXMin, f3D2DXCoef); iT = (int) XDM_to2D(vVect2.y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y iX = (int) XDM_to2D(vVect1.z, fZmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); iZ = (int) XDM_to2D(vVect2.z, fZmin, iWindowXMin, f3D2DXCoef); iT = (int) XDM_to2D(vVect2.y, fYmin, iWindowYMin, f3D2DYCoef); break; } // Tracer l'arête MoveToEx(hdcDoubleBuf, iX, iY, NULL); LineTo(hdcDoubleBuf, iZ, iT); } // 2 - Triangles // Choisir le crayon rose SelectObject(hdcDoubleBuf, hpenPink); for (int iTriangle = 0 ; iTriangle <= iTriaLastUsed ; iTriangle++) { // Ignorer les triangles inexistants if (Triangles[iTriangle].bEnabled == FALSE) continue; // Ignorer les triangles cachés if (Triangles[iTriangle].bHidden == TRUE) continue; // Pour chaque coté du triangle (on ne trace que les 3 premiers, les 3 suivants étant les mêmes dans un ordre différent) for (int iSommet = 0 ; iSommet < 3 ; iSommet++) { // Déterminer les coordonnées de la projection du segment (sommet, sommet suivant) sur la fenêtre en cours // --> segment (iX, iY) - (iZ, iT) int iSommetSuivant = (iSommet + 1) % 3; vVect1 = Vertices[Triangles[iTriangle].iSommets[iSommet]].vPoint; vVect2 = Vertices[Triangles[iTriangle].iSommets[iSommetSuivant]].vPoint; switch(lWActive) { case XDC_WID_TOP : // X et Z iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(vVect1.z, fZmin, iWindowYMin, f3D2DYCoef); iZ = (int) XDM_to2D(vVect2.x, fXmin, iWindowXMin, f3D2DXCoef); iT = (int) XDM_to2D(vVect2.z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); iZ = (int) XDM_to2D(vVect2.x, fXmin, iWindowXMin, f3D2DXCoef); iT = (int) XDM_to2D(vVect2.y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y iX = (int) XDM_to2D(vVect1.z, fZmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); iZ = (int) XDM_to2D(vVect2.z, fZmin, iWindowXMin, f3D2DXCoef); iT = (int) XDM_to2D(vVect2.y, fYmin, iWindowYMin, f3D2DYCoef); break; } // Tracer l'arête du triangle MoveToEx(hdcDoubleBuf, iX, iY, NULL); LineTo(hdcDoubleBuf, iZ, iT); } } // 3.1 - Points for (int iVertex = 0 ; iVertex <= iVertLastUsed ; iVertex++) { // Ignorer les points inexistants if (Vertices[iVertex].bEnabled == FALSE) continue; // Ignorer les points cachés if (Vertices[iVertex].bHidden == TRUE) continue; vVect1 = Vertices[iVertex].vPoint; switch(lWActive) { case XDC_WID_TOP : // X et Z iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(vVect1.z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y iX = (int) XDM_to2D(vVect1.z, fZmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); break; } // Tracer le sommet du triangle (petite croix) lColor = Vertices[iVertex].bSelected ? XDC_COL_YELLOW : XDC_COL_DKBLUESK; SetPixel(hdcDoubleBuf, iX, iY, lColor); SetPixel(hdcDoubleBuf, iX - 1, iY, lColor); SetPixel(hdcDoubleBuf, iX + 1, iY, lColor); SetPixel(hdcDoubleBuf, iX, iY - 1, lColor); SetPixel(hdcDoubleBuf, iX, iY + 1, lColor); } // 3.2 - VertexBuffers des objets de base for (int iObject = 0 ; iObject <= iObjtLastUsed ; iObject++) { if (Objects[iObject].bEnabled == FALSE) continue; if (Objects[iObject].bHidden == TRUE) continue; LPDIRECT3DVERTEXBUFFER7 vBuf = Objects[iObject].pShape -> GetVB(); D3DVERTEXBUFFERDESC vbDesc; vbDesc.dwSize = sizeof(vbDesc); vBuf -> GetVertexBufferDesc(&vbDesc); if (vbDesc.dwFVF != D3DFVF_VERTEX) continue; D3DVERTEX *vbAddr; unsigned long iSize; vBuf -> Lock(DDLOCK_SURFACEMEMORYPTR, (void **) &vbAddr, &iSize); for (unsigned iVertex = 0 ; iVertex < vbDesc.dwNumVertices ; iVertex++) { switch(lWActive) { case XDC_WID_TOP : // X et Z iX = (int) XDM_to2D(vbAddr[iVertex].x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(vbAddr[iVertex].z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y iX = (int) XDM_to2D(vbAddr[iVertex].x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(vbAddr[iVertex].y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y iX = (int) XDM_to2D(vbAddr[iVertex].z, fZmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(vbAddr[iVertex].y, fYmin, iWindowYMin, f3D2DYCoef); break; } // Tracer le point (petite croix) lColor = Objects[iObject].bSelected ? XDC_COL_YELLOW : XDC_COL_DKPINK; SetPixel(hdcDoubleBuf, iX, iY, lColor); SetPixel(hdcDoubleBuf, iX - 1, iY, lColor); SetPixel(hdcDoubleBuf, iX + 1, iY, lColor); SetPixel(hdcDoubleBuf, iX, iY - 1, lColor); SetPixel(hdcDoubleBuf, iX, iY + 1, lColor); } vBuf -> Unlock(); vBuf -> Release(); // Tracer l'origine de l'objet (qui sert aussi de handle) switch(lWActive) { case XDC_WID_TOP : // X et Z iX = (int) XDM_to2D(Objects[iObject].vOrigin.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(Objects[iObject].vOrigin.z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y iX = (int) XDM_to2D(Objects[iObject].vOrigin.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(Objects[iObject].vOrigin.y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y iX = (int) XDM_to2D(Objects[iObject].vOrigin.z, fZmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(Objects[iObject].vOrigin.y, fYmin, iWindowYMin, f3D2DYCoef); break; } // Tracer le point (petite croix) lColor = Objects[iObject].bSelected ? XDC_COL_YELLOW : XDC_COL_GREEN; SetPixel(hdcDoubleBuf, iX - 1, iY, lColor); SetPixel(hdcDoubleBuf, iX + 1, iY, lColor); SetPixel(hdcDoubleBuf, iX, iY - 1, lColor); SetPixel(hdcDoubleBuf, iX, iY + 1, lColor); } // 4 - Lampes for (int iLamp = 0 ; iLamp <= iLampLastUsed ; iLamp++) { // Ignorer les lampes inexistantes if (Lampes[iLamp].bEnabled == FALSE) continue; if (Lampes[iLamp].bSelected == FALSE) SelectObject(hdcDoubleBuf, hpenRed); else SelectObject(hdcDoubleBuf, hpenYellow); vVect1 = Lampes[iLamp].lLamp.dvPosition; switch(lWActive) { case XDC_WID_TOP : // X et Z iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(vVect1.z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y iX = (int) XDM_to2D(vVect1.z, fZmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef); break; } Ellipse(hdcDoubleBuf, iX - 3, iY - 3, iX + 3, iY + 3); } // Libérer le clipping du double buffer SelectClipRgn(hdcDoubleBuf, NULL); // Restaurer les objets par défaut du double buffer SelectObject(hdcDoubleBuf, hSaveBrush); SelectObject(hdcDoubleBuf, hSavePen); } _skip: // BitBlitter le double buffer dans le triple buffer BitBlt(hdcTripleBuf, 0, 0, rExtRect.right - rExtRect.left, rExtRect.bottom - rExtRect.top, hdcDoubleBuf, 0, 0, SRCCOPY); // Définir zone de clipping du triple buffer : rectangle interne IntersectClipRect(hdcTripleBuf,iWindowXMin + 1, iWindowYMax + 1, iWindowXMax - 1, iWindowYMin - 1); // 5 - Tracer le curseur principal switch(lWActive) { case XDC_WID_TOP : // X et Z iX = (int) XDM_to2D(Cursor1.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(Cursor1.z, fZmin, iWindowYMin, f3D2DYCoef); iZ = (int) XDM_to2D(Cursor1.x - (fXmax - fXmin) / XDC_ZONE, fXmin, iWindowXMin, f3D2DXCoef); iT = (int) XDM_to2D(Cursor1.z - (fXmax - fXmin) / XDC_ZONE, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y iX = (int) XDM_to2D(Cursor1.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(Cursor1.y, fYmin, iWindowYMin, f3D2DYCoef); iZ = (int) XDM_to2D(Cursor1.x - (fXmax - fXmin) / XDC_ZONE, fXmin, iWindowXMin, f3D2DXCoef); iT = (int) XDM_to2D(Cursor1.y - (fXmax - fXmin) / XDC_ZONE, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y iX = (int) XDM_to2D(Cursor1.z, fZmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(Cursor1.y, fYmin, iWindowYMin, f3D2DYCoef); iZ = (int) XDM_to2D(Cursor1.z - (fXmax - fXmin) / XDC_ZONE, fZmin, iWindowXMin, f3D2DXCoef); iT = (int) XDM_to2D(Cursor1.y - (fXmax - fXmin) / XDC_ZONE, fYmin, iWindowYMin, f3D2DYCoef); break; } hSavePen = (HPEN) SelectObject(hdcTripleBuf, (cTool == XDC_TOOL_UNSELECT ? hpenDkBlueSk : hpenYellow)); // Tracer la zone de tolérance MoveToEx(hdcTripleBuf, iZ, iT, NULL); LineTo(hdcTripleBuf, iZ + 2 * (iX - iZ), iT); MoveToEx(hdcTripleBuf, iZ, iT, NULL); LineTo(hdcTripleBuf, iZ, iT + 2 * (iY - iT)); if ((cTool == XDC_TOOL_SELECT) || (cTool == XDC_TOOL_UNSELECT)) { MoveToEx(hdcTripleBuf, iZ, iT + 2 * (iY - iT), NULL); LineTo(hdcTripleBuf, iZ + 2 * (iX - iZ), iT + 2 * (iY - iT)); MoveToEx(hdcTripleBuf, iZ + 2 * (iX - iZ), iT, NULL); LineTo(hdcTripleBuf, iZ + 2 * (iX - iZ), iT + 2 * (iY - iT)); } // Rappeller l'outil courant à coté du curseur if (cTool != XDC_TOOL_NONE) ExtTextOut(hdcTripleBuf, iX + 2, iY - 13, 0, NULL, &cTool, 1, NULL); // Tracer le curseur 1 SelectObject(hdcTripleBuf, hpenCyan); MoveToEx(hdcTripleBuf, iX - 9, iY, NULL); LineTo(hdcTripleBuf, iX + 10, iY); MoveToEx(hdcTripleBuf, iX, iY - 9, NULL); LineTo(hdcTripleBuf, iX, iY + 10); // 6 - Tracer le curseur 2 switch(lWActive) { case XDC_WID_TOP : // X et Z iX = (int) XDM_to2D(Cursor2.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(Cursor2.z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y iX = (int) XDM_to2D(Cursor2.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(Cursor2.y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y iX = (int) XDM_to2D(Cursor2.z, fZmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(Cursor2.y, fYmin, iWindowYMin, f3D2DYCoef); break; } Ellipse(hdcTripleBuf, iX - 3, iY - 3, iX + 3, iY + 3); // 7 - Tracer le curseur 3 switch(lWActive) { case XDC_WID_TOP : // X et Z iX = (int) XDM_to2D(Cursor3.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(Cursor3.z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y iX = (int) XDM_to2D(Cursor3.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(Cursor3.y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y iX = (int) XDM_to2D(Cursor3.z, fZmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(Cursor3.y, fYmin, iWindowYMin, f3D2DYCoef); break; } MoveToEx(hdcTripleBuf, iX - 4, iY - 4, NULL); LineTo(hdcTripleBuf, iX + 5, iY + 5); MoveToEx(hdcTripleBuf, iX - 4, iY + 4, NULL); LineTo(hdcTripleBuf, iX + 5, iY - 5); // 8 - Tracer l'observateur SelectObject(hdcTripleBuf, hpenWhite); switch(lWActive) { case XDC_WID_TOP : // X et Z iX = (int) XDM_to2D(Observer.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(Observer.z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y iX = (int) XDM_to2D(Observer.x, fXmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(Observer.y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y iX = (int) XDM_to2D(Observer.z, fZmin, iWindowXMin, f3D2DXCoef); iY = (int) XDM_to2D(Observer.y, fYmin, iWindowYMin, f3D2DYCoef); break; } Ellipse(hdcTripleBuf, iX - 2, iY - 2, iX + 3, iY + 3); // 9 - Tracer la cible et le segment caméra / cible switch(lWActive) { case XDC_WID_TOP : // X et Z iZ = (int) XDM_to2D(Target.x, fXmin, iWindowXMin, f3D2DXCoef); iT = (int) XDM_to2D(Target.z, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y iZ = (int) XDM_to2D(Target.x, fXmin, iWindowXMin, f3D2DXCoef); iT = (int) XDM_to2D(Target.y, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y iZ = (int) XDM_to2D(Target.z, fZmin, iWindowXMin, f3D2DXCoef); iT = (int) XDM_to2D(Target.y, fYmin, iWindowYMin, f3D2DYCoef); break; } MoveToEx(hdcTripleBuf, iZ - 2, iT - 2, NULL); LineTo(hdcTripleBuf, iZ + 3, iT + 3); MoveToEx(hdcTripleBuf, iZ - 2, iT + 2, NULL); LineTo(hdcTripleBuf, iZ + 3, iT - 3); MoveToEx(hdcTripleBuf, iX, iY, NULL); LineTo(hdcTripleBuf, iZ, iT); // 10 - Coordonnées courantes if (bCoords) { sprintf(cCoords, "(%012.5f, %012.5f, %012.5f)", vTracker.x, vTracker.y, vTracker.z); ExtTextOut(hdcTripleBuf, 18, 10, 0, NULL, cCoords, strlen(cCoords), NULL); } // Libérer le clipping du triple buffer SelectClipRgn(hdcTripleBuf, NULL); // BitBlitter le triple buffer dans la fenêtre BitBlt(hdcWin, rExtRect.left, rExtRect.top, rExtRect.right - rExtRect.left, rExtRect.bottom - rExtRect.top, hdcTripleBuf, 0, 0, SRCCOPY); // Restaurer les objets par défaut du triple buffer SelectObject(hdcTripleBuf, hSavePen); EndPaint(hWnd, &hPStruct); break; } case WM_LBUTTONDOWN : //**************** C L I C K G A U C H E ******************* RECT rClipCurseur; // Si on est déjà en tracking curseur alors ne rien faire if (bTracking) break; // Noter le qualifier (touches enfoncées au moment du click) wModifier = wParam; // Précalculer les offsets (déplacement, zoom, etc.) en fonction du modifieur fXs = (fXmax - fXmin) / ((wModifier & MK_SHIFT) ? 4.f : 8.f), fYs = (fYmax - fYmin) / ((wModifier & MK_SHIFT) ? 4.f : 8.f), fZs = (fZmax - fZmin) / ((wModifier & MK_SHIFT) ? 4.f : 8.f); // Vérifier si le click n'est pas dans les boutons Sculpt. pClick.x = LOWORD(lParam); pClick.y = HIWORD(lParam); if (XDM_BoutonClic(XDC_GID_MakeTri, pClick)) //********* Bouton MakeTri { int iPoint[3], iPoints = 0; // Compter et mémoriser les points sélectionnés (jusqu'à 3) for (int iVertex = 0 ; iVertex <= iVertLastUsed ; iVertex++) if (bIsVertexSelected(iVertex)) { if (iPoints < 3) iPoint[iPoints] = iVertex; iPoints++; } // - soit il existe exactement 2 points sélectionnés et on fait une arête avec // si elle n'existe pas déjà // (on ne transforme pas 3 points reliés par 3 arêtes en triangle ***???) if (iPoints == 2) { vTrace("Deux points sélectionnés -> création arête"); if (-1 == iFindEdge(iPoint[0], iPoint[1])) { iMakeEdge(iPoint[0], iPoint[1]); vForce2DRefresh(XDC_MODE_COMPLET); vForce3DRefresh(XDC_MODE_COMPLET); } else vTrace("*** E0001 : L'arête existe déjà"); break; } // - soit il existe exactement 3 points sélectionnés et on fait un triangle avec // (en supprimant les arêtes éventuelles existant entre ces 3 points) s'il n'existe pas déjà if (iPoints == 3) { vTrace("Trois points sélectionnés -> création facette"); if (-1 == iFindTriangle(iPoint[0], iPoint[1], iPoint[2])) { iMakeTriangle(iPoint[0], iPoint[1], iPoint[2], rand() * 255 / RAND_MAX, rand() * 255 / RAND_MAX, rand() * 255 / RAND_MAX); vForce2DRefresh(XDC_MODE_COMPLET); vForce3DRefresh(XDC_MODE_COMPLET); } else vTrace("*** E0002 : Le triangle existe déjà"); break; } // - soit il existe exactement 0 points sélectionnés et on fait un triangle entre // les 3 curseurs s'il n'existe pas déjà if (iPoints == 0) { vTrace("Zéro points sélectionnés -> création facette avec les 3 curseurs"); iPoint[0] = iMakeVertex(Cursor2, XDC_ALLOWSAME), iPoint[1] = iMakeVertex(Cursor1, XDC_ALLOWSAME), iPoint[2] = iMakeVertex(Cursor3, XDC_ALLOWSAME); if (-1 == iFindTriangle(iPoint[0], iPoint[1], iPoint[2])) { iMakeTriangle(iPoint[0], iPoint[1], iPoint[2], rand() * 255 / RAND_MAX, rand() * 255 / RAND_MAX, rand() * 255 / RAND_MAX); vForce2DRefresh(XDC_MODE_COMPLET); vForce3DRefresh(XDC_MODE_COMPLET); } else vTrace("*** E0003 : Le triangle existe déjà"); break; } vTrace("*** E0004 : Nombre de points sélectionnés incorrect (doit être 0, 2 ou 3)"); break; } if (XDM_BoutonClic(XDC_GID_ZoomOut, pClick)) //********* Bouton Zoom Out { fXmin -= fXs; fXmax += fXs; fYmin -= fYs; fYmax += fYs; fZmin -= fZs; fZmax += fZs; vForce2DRefresh(XDC_MODE_COMPLET); break; } if (XDM_BoutonClic(XDC_GID_ZoomIn, pClick)) //********* Bouton Zoom In { fXmin += fXs; fXmax -= fXs; fYmin += fYs; fYmax -= fYs; fZmin += fZs; fZmax -= fZs; vForce2DRefresh(XDC_MODE_COMPLET); break; } if ( (XDM_BoutonClic(XDC_GID_RotClock, pClick)) //********* Bouton Rotation clockwise || (XDM_BoutonClic(XDC_GID_RotAnti, pClick)) //********* Bouton Rotation anti-clockwise ) { D3DMATRIX mRot; float fAngle = g_PI / (wModifier & MK_SHIFT ? 10.f : 20.f); if (XDM_BoutonClic(XDC_GID_RotClock, pClick)) fAngle *= -1.f; // Préparer la matrice de rotation switch(lWActive) { case XDC_WID_TOP : // X et Z D3DUtil_SetRotateYMatrix(mRot, -fAngle); break; case XDC_WID_FACE : // X et Y D3DUtil_SetRotateZMatrix(mRot, fAngle); break; case XDC_WID_SIDE : // Z et Y D3DUtil_SetRotateXMatrix(mRot, -fAngle); break; } // Appliquer la matrice aux sommets sélectionnés for (int iVertex = 0 ; iVertex <= iVertLastUsed ; iVertex++) if (bIsVertexSelected(iVertex)) { // Changer de repère => Cursor1 D3DVECTOR vTrans = Vertices[iVertex].vPoint - Cursor1; // Appliquer la rotation au point translaté D3DMath_VectorMatrixMultiply(vTrans, vTrans, mRot); // Remettre dans le repère d'origine Vertices[iVertex].vPoint = vTrans + Cursor1; } // Recalculer les sommets des triangles ayant des sommets sélectionnés for (int iTriangle = 0 ; iTriangle <= iTriaLastUsed ; iTriangle++) if (bIsTrianglePartiallySelected(iTriangle)) bUpdateD3DTri(iTriangle); // Appliquer la matrice de rotation aux objets D3D sélectionnés for (int iObject = 0 ; iObject <= iObjtLastUsed ; iObject++) if ((Objects[iObject].bEnabled) && (Objects[iObject].bSelected)) { LPDIRECT3DVERTEXBUFFER7 vBuf = Objects[iObject].pShape -> GetVB(); D3DVERTEXBUFFERDESC vbDesc; D3DVECTOR vTrans; vbDesc.dwSize = sizeof(vbDesc); vBuf -> GetVertexBufferDesc(&vbDesc); if (vbDesc.dwFVF != D3DFVF_VERTEX) return FALSE; D3DVERTEX *vbAddr; unsigned long iSize; vBuf -> Lock(DDLOCK_SURFACEMEMORYPTR, (void **) &vbAddr, &iSize); for (unsigned iVertex = 0 ; iVertex < vbDesc.dwNumVertices ; iVertex++) { // A - Traiter le point // Changer de repère => Cursor1 vTrans = D3DVECTOR( vbAddr[iVertex].x - Cursor1.x, vbAddr[iVertex].y - Cursor1.y, vbAddr[iVertex].z - Cursor1.z); // Appliquer la rotation au point translaté D3DMath_VectorMatrixMultiply(vTrans, vTrans, mRot); // Remettre dans le repère d'origine vTrans += Cursor1; vbAddr[iVertex].x = vTrans.x; vbAddr[iVertex].y = vTrans.y; vbAddr[iVertex].z = vTrans.z; // B - Traiter le vecteur normal vTrans = D3DVECTOR( vbAddr[iVertex].nx, vbAddr[iVertex].ny, vbAddr[iVertex].nz); D3DMath_VectorMatrixMultiply(vTrans, vTrans, mRot); vbAddr[iVertex].nx = vTrans.x; vbAddr[iVertex].ny = vTrans.y; vbAddr[iVertex].nz = vTrans.z; } vBuf -> Unlock(); vBuf -> Release(); // Traiter l'origine locale objet vTrans = Objects[iObject].vOrigin - Cursor1; D3DMath_VectorMatrixMultiply(vTrans, vTrans, mRot); Objects[iObject].vOrigin = vTrans + Cursor1; } // Raffraichir les vues 2D et 3D vForce2DRefresh(XDC_MODE_COMPLET); vForce3DRefresh(XDC_MODE_COMPLET); break; } if (XDM_BoutonClic(XDC_GID_Reverse, pClick)) // ********* Bouton reverse (?) { // vForce2DRefresh(XDC_MODE_COMPLET); break; } if (XDM_BoutonClic(XDC_GID_Grab, pClick)) // ********* Bouton Grabber (toggle) { cTool = (cTool == XDC_TOOL_GRAB ? XDC_TOOL_NONE : XDC_TOOL_GRAB); vForce2DRefresh(XDC_MODE_PARTIEL); vUpdateMenu(); break; } if (XDM_BoutonClic(XDC_GID_GoRight, pClick)) //********* Bouton Go Right { switch(lWActive) { case XDC_WID_TOP : // X et Z case XDC_WID_FACE : // X et Y fXmin += fXs; fXmax += fXs; break; case XDC_WID_SIDE : // Z et Y fZmin += fZs; fZmax += fZs; break; } vForce2DRefresh(XDC_MODE_COMPLET); break; } if (XDM_BoutonClic(XDC_GID_GoUp, pClick)) //********* Bouton Go up { switch(lWActive) { case XDC_WID_TOP : // X et Z fZmin += fZs; fZmax += fZs; break; case XDC_WID_FACE : // X et Y case XDC_WID_SIDE : // Z et Y fYmin += fYs; fYmax += fYs; break; } vForce2DRefresh(XDC_MODE_COMPLET); break; } if (XDM_BoutonClic(XDC_GID_GoLeft, pClick)) //********* Bouton Go left { switch(lWActive) { case XDC_WID_TOP : // X et Z case XDC_WID_FACE : // X et Y fXmin -= fXs; fXmax -= fXs; break; case XDC_WID_SIDE : // Z et Y fZmin -= fZs; fZmax -= fZs; break; } vForce2DRefresh(XDC_MODE_COMPLET); break; } if (XDM_BoutonClic(XDC_GID_GoDown, pClick)) //********* Bouton Go down { switch(lWActive) { case XDC_WID_TOP : // X et Z fZmin -= fZs; fZmax -= fZs; break; case XDC_WID_FACE : // X et Y case XDC_WID_SIDE : // Z et Y fYmin -= fYs; fYmax -= fYs; break; } vForce2DRefresh(XDC_MODE_COMPLET); break; } if (XDM_BoutonClic(XDC_GID_AddPoint, pClick)) //********* Bouton Add Point { PostMessage(hWnd, WM_CHAR, 'p', 0); break; } if (XDM_BoutonClic(XDC_GID_Center, pClick)) //********* Bouton Center { float fXs = (fXmax - fXmin) / 2.f, fYs = (fYmax - fYmin) / 2.f, fZs = (fZmax - fZmin) / 2.f; fXmin = Cursor1.x - fXs; fXmax = Cursor1.x + fXs; fYmin = Cursor1.y - fYs; fYmax = Cursor1.y + fYs; fZmin = Cursor1.z - fZs; fZmax = Cursor1.z + fZs; vForce2DRefresh(XDC_MODE_COMPLET); break; } // Si click dans le rectangle interne, alors : // - déclencher le tracking (curseur, observer ou target en fonction du qualifier // - n'autoriser le déplacement que dans le subrect client (clipcursor) // - initialiser le tracking (MOUSEMOVE) if (PtInRect(&rIntRect, pClick)) { CopyRect(&rClipCurseur, &rIntRect); ClientToScreen(hWnd, (POINT *) &rClipCurseur); ClientToScreen(hWnd, (POINT *) &rClipCurseur + 1); ClipCursor(&rClipCurseur); bTracking = TRUE; PostMessage(hWnd, WM_MOUSEMOVE, wParam, lParam); break; } // Click dans zone cliente, ni rectangle interne ni gadgets sKulpt : popup menu // avec menu édition hMenu = GetSubMenu(GetMenu(hWndMenu), 1); ClientToScreen(hWnd, &pClick); TrackPopupMenu (hMenu, 0, pClick.x, pClick.y, 0, hWnd, NULL); break; case WM_LBUTTONDBLCLK: pClick.x = LOWORD(lParam); pClick.y = HIWORD(lParam); // Si le double click est dans le rectangle interne alors toggler la sélection du noeud indiqué // en envoyant le message ID_EDITION_SLECTIONNER_NOEUDINDIQU à la fenêtre menu avec lParam = XDC_TOGGLE // Sinon, traiter le message comme un simple click if (PtInRect(&rIntRect, pClick)) PostMessage(hWndMenu, WM_COMMAND, ID_EDITION_SLECTIONNER_NOEUDINDIQU, XDC_SINGLETOGGLE); else PostMessage(hWnd, WM_LBUTTONDOWN, wParam, lParam); break; case WM_LBUTTONUP : //******************** R E L A C H E B O U T O N G A U C H E ****** // Si on n'est pas en mode tracking, ne rien faire // (ou envoyer les coordonnées à la dlg d'acquisition des trous des formes à remplir si elle est active). if (hHoleDlgActive) { switch(lWActive) { case XDC_WID_TOP : // X et Z dHoles[iHoles * 2 + 0] = XDM_to3D(LOWORD(lParam), fXmin, iWindowXMin, f3D2DXCoef); dHoles[iHoles * 2 + 1] = XDM_to3D(HIWORD(lParam), fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y dHoles[iHoles * 2 + 0] = XDM_to3D(LOWORD(lParam), fXmin, iWindowXMin, f3D2DXCoef); dHoles[iHoles * 2 + 1] = XDM_to3D(HIWORD(lParam), fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y dHoles[iHoles * 2 + 0] = XDM_to3D(LOWORD(lParam), fZmin, iWindowXMin, f3D2DXCoef); dHoles[iHoles * 2 + 1] = XDM_to3D(HIWORD(lParam), fYmin, iWindowYMin, f3D2DYCoef); break; } iHoles++; SendMessage(hHoleDlgActive, WM_USER+1, 0, 0); } if (!bTracking) break; // Si on est en mode tracking, arrêter le mode tracking et supprimer le clipping. bTracking = FALSE; ClipCursor(NULL); break; case WM_CHAR : //************************* F R A P P E C L A V I E R ******************** PostMessage(hWndMenu, uMsg, wParam, lParam); break; case WM_MOUSEMOVE : //****************** M O U V E M E N T S O U R I S ************* D3DVECTOR *pObject; // Si on n'est pas en tracking alors on ne fait rien. if (!bTracking) break; // Déterminer l'objet à déplacer en fonction des qualifiers du WM_LBUTTONDOWN pObject = &Cursor1; if (wModifier & MK_MBUTTON) pObject = &Target; if (wModifier & MK_RBUTTON) pObject = &Observer; if (wModifier & MK_CONTROL) pObject = &Cursor2; if (wModifier & MK_SHIFT) pObject = &Cursor3; // Mémoriser l'ancien vecteur vVect1 = *pObject; // Déterminer les nouvelles coordonnées 2D de l'objet à déplacer iX = LOWORD(lParam); // horizontal position iY = HIWORD(lParam); // vertical position // Mettre à jour les coordonnées 3D de l'objet à déplacer switch(lWActive) { case XDC_WID_TOP : // X et Z pObject -> x = XDM_to3D(iX, fXmin, iWindowXMin, f3D2DXCoef); pObject -> z = XDM_to3D(iY, fZmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_FACE : // X et Y pObject -> x = XDM_to3D(iX, fXmin, iWindowXMin, f3D2DXCoef); pObject -> y = XDM_to3D(iY, fYmin, iWindowYMin, f3D2DYCoef); break; case XDC_WID_SIDE : // Z et Y pObject -> z = XDM_to3D(iX, fZmin, iWindowXMin, f3D2DXCoef); pObject -> y = XDM_to3D(iY, fYmin, iWindowYMin, f3D2DYCoef); break; } // Si la grille est activée, snapper l'objet à la grille (en x/y/z) if (bGrid) { pObject -> x = XDM_toGrid(pObject -> x); pObject -> y = XDM_toGrid(pObject -> y); pObject -> z = XDM_toGrid(pObject -> z); } // Mémoriser les coordonnées pour l'affichage des coordonnées if (bCoords) vTracker = *pObject; // Si on a déplacé l'observer ou le target, mettre à jour la VIEW MATRIX // (la vue 3D se met automatiquement à jour par timer dans 3dwndproc) if ((pObject == &Target) || (pObject == &Observer)) { D3DUtil_SetViewMatrix(matView, Observer, // From Target, // To D3DVECTOR(0.f, 0.f, 0.f)); // Mettre à jour les variables d'état du pipe D3D vSetD3DState(); // Recalculer la scène vForce3DRefresh(XDC_MODE_COMPLET); } // Si on a un outil sélectionné, appliquer l'outil à la sélection if ((pObject == &Cursor1) && (cTool != XDC_TOOL_NONE)) { switch(cTool) { case XDC_TOOL_SELECT: PostMessage(hWndMenu, WM_COMMAND, ID_EDITION_SLECTIONNER_NOEUDINDIQU, XDC_SELECTALL); break; case XDC_TOOL_UNSELECT: PostMessage(hWndMenu, WM_COMMAND, ID_EDITION_SLECTIONNER_NOEUDINDIQU, XDC_DESELECTALL); break; case XDC_TOOL_MAGNET: break; case XDC_TOOL_CURVE: break; case XDC_TOOL_EXTRUDE: break; case XDC_TOOL_EDGE: break; case XDC_TOOL_GRAB: { BOOL bShouldDo = FALSE; // Faire suivre le mouvement du curseur à tous les vertices sélectionnés for (int iVertex = 0 ; iVertex <= iVertLastUsed ; iVertex++) { if (bIsVertexSelected(iVertex)) { Vertices[iVertex].vPoint += (Cursor1 - vVect1); bShouldDo = TRUE; } } // Recalculer tous les triangles modifiés if (bShouldDo) for (int iTriangle = 0 ; iTriangle <= iTriaLastUsed ; iTriangle++) if (bIsTrianglePartiallySelected(iTriangle)) bUpdateD3DTri(iTriangle); } // Faire suivre le mouvement du curseur à toutes les lampes sélectionnées for (int iLamp = 0 ; iLamp <= iLampLastUsed ; iLamp++) { if (Lampes[iLamp].bEnabled == FALSE) continue; if (Lampes[iLamp].bSelected == FALSE) continue; Lampes[iLamp].lLamp.dvPosition += (Cursor1 - vVect1); bUpdateLamp(iLamp); } // Faire suivre le mouvement du curseur à tous les objets D3D sélectionnés for (int iObject = 0 ; iObject <= iObjtLastUsed ; iObject++) { if (Objects[iObject].bEnabled == FALSE) continue; if (Objects[iObject].bSelected == FALSE) continue; bMoveD3DObj(iObject, Cursor1 - vVect1); } vForce2DRefresh(XDC_MODE_COMPLET); vForce3DRefresh(XDC_MODE_COMPLET); goto _break; } } // Forcer le redessin des fenêtres 2D pour prendre en compte le déplacement de l'objet vForce2DRefresh(XDC_MODE_PARTIEL); _break: break; case WM_SIZE: //**************** T A I L L E F E N E T R E **************** // Détruire et recréer le double buffer avec les nouvelles dimensions de la fenêtre iX = LOWORD(lParam); // width of client area iY = HIWORD(lParam); // height of client area SelectObject(pWT -> hdcDBuf, pWT -> holdDBuf); DeleteObject(pWT -> hbDBuf); SelectObject(pWT -> hdcTBuf, pWT -> holdTBuf); DeleteObject(pWT -> hbTBuf); if (!(pWT -> hbDBuf = CreateCompatibleBitmap(hdcWin, iX, iY))) { PostQuitMessage(0); break; } pWT -> holdDBuf = SelectObject(pWT -> hdcDBuf, pWT -> hbDBuf); if (!(pWT -> hbTBuf = CreateCompatibleBitmap(hdcWin, iX, iY))) { PostQuitMessage(0); break; } pWT -> holdTBuf = SelectObject(pWT -> hdcTBuf, pWT -> hbTBuf); // Forcer le redessin complet de la fenêtre PostMessage(hWnd, WM_PAINT, 0, (LPARAM) TRUE); break; case WM_GETMINMAXINFO: // Prevent the window from going smaller than some minimum size ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100; ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100; break; case WM_NCLBUTTONDBLCLK : ShowWindow(hWnd, SW_SHOWMAXIMIZED); break; case WM_COMMAND: PostMessage(hWndMenu, uMsg, wParam, lParam ); break; // case WM_CLOSE: // (ne devrait jamais survenir : pas de close gadget) case WM_DESTROY: // Libérer les objets GDI if (hpenWhite) { DeleteObject(hpenWhite); hpenWhite = NULL; } if (hpenRed) { DeleteObject(hpenRed); hpenRed = NULL; } if (hpenYellow) { DeleteObject(hpenYellow); hpenYellow = NULL; } if (hpenCyan) { DeleteObject(hpenCyan); hpenCyan = NULL; } if (hpenPink) { DeleteObject(hpenPink); hpenPink = NULL; } if (hpenGrey) { DeleteObject(hpenGrey); hpenGrey = NULL; } if (hbrDkBlueSk) { DeleteObject(hbrDkBlueSk); hbrDkBlueSk = NULL; } if (hbrLtBlueSk) { DeleteObject(hbrLtBlueSk); hbrLtBlueSk = NULL; } if (hpenDkBlueSk) { DeleteObject(hpenDkBlueSk); hpenDkBlueSk = NULL; } // Détruire le double buffer SelectObject(pWT -> hdcDBuf, pWT -> holdDBuf); SelectObject(pWT -> hdcDBuf, pWT -> holdDFont); DeleteObject(pWT -> hbDBuf); DeleteDC(pWT -> hdcDBuf); // Détruire le triple buffer SelectObject(pWT -> hdcTBuf, pWT -> holdTBuf); SelectObject(pWT -> hdcTBuf, pWT -> holdTBrush); SelectObject(pWT -> hdcTBuf, pWT -> holdTFont); DeleteObject(pWT -> hbTBuf); DeleteDC(pWT -> hdcTBuf); // Détruire la structure de données attachée à la fenêtre free(pWT); // Libérer le HDC de la fenêtre ReleaseDC(hWnd, hdcWin); // PostQuitMessage(0); return 0L; } // Libérer le HDC de la fenêtre ReleaseDC(hWnd, hdcWin); return DefWindowProc( hWnd, uMsg, wParam, lParam ); }